/******************************************************************************

    Copyright (C) 2019 ErisedMedia
    All Rights Reserved.

    This source code and any compilation or derivative thereof is the
    proprietary information of ErisedMedia and is
    confidential in nature.
    Under no circumstances is this software to be exposed to or placed under an
    Open Source License of any type without the expressed written permission of
    ErisedMedia.

******************************************************************************/

/******************************************************************************

    File:   FaceRecDB.h
    Brief:  FaceRecDB的头文件，人脸识别.

******************************************************************************/

/******************************************************************************

    Rev     Date        Author      Comments
--------------------------------------------------------------------------------
    001     20190526    RunyuanYe        Original

--------------------------------------------------------------------------------
    For consistency and standardisation retain the Section Separators.

*******************************************************************************/
#ifndef _FACE_REC_DB_H_
#define _FACE_REC_DB_H_

/******************************************************************************
*
*   CONFIG MACROS
*
******************************************************************************/


/******************************************************************************
*
*   INCLUDE FILES
*
******************************************************************************/


/******************************************************************************
*
*   MACROS
*
******************************************************************************/

#define FACE_FEATURE_SIZE       1024

// 每个人脸最大保存的特征数量
#define MAX_FEATURE_COUNT_PRE_FACE  64

#define FACE_REC_DB_SIMILARITY_TOPK     128
#define FACE_REC_DB_SAME_FACE_SCORE_THR 0.331

#define FaceRecStatus_Register  0   // 注册新人脸到人脸库
#define FaceRecStatus_Add       1   // 添加到已有人脸
#define FaceRecStatus_Update    2   // 更新替换已有人脸
#define FaceRecStatus_Match     3   // 匹配到人脸库的人脸

/******************************************************************************
*
*   TYPEDEFS
*
******************************************************************************/

typedef struct _FaceFeatureInfo
{
    char        feature[FACE_FEATURE_SIZE];
    int         featureSize;
    long long   idx;
    long long   faceId;
    long long   matchCount;
    std::string path;
} FaceFeatureInfo;

typedef struct _FaceRecDBParam
{
    shared_ptr<FaceFeatureInfo> info;
} FaceRecDBParam;

typedef struct _FaceRecDBResult
{
    int         status;
    float       score;      // 表示为此人脸的可信程度
    string      uuid;
    long long   id;
    long long   faceId;
} FaceRecDBResult;

/*
    特征比较回调函数类型

    feature1: 输入特征1
    feature2: 输入特征2
    featureSize: 特征长度
    context: 为上下文参数

    返回相似性得分
*/
typedef float (*FeatureCompareCB)(void* feature1, void* feature2, int featureSize, void* context);

/******************************************************************************
*
*   EXPORT DATA
*
******************************************************************************/


/******************************************************************************
*
*   EXPORT FUNCTION PROTOTYPES
*
******************************************************************************/


class FaceRecDB
{
public:
    FaceRecDB(float sameFaceScoreThreshold=FACE_REC_DB_SAME_FACE_SCORE_THR, int similarityTopK=FACE_REC_DB_SIMILARITY_TOPK, int searchMode=0, int searchThreadnum=1);
    ~FaceRecDB();

    int SearchFaceRecDB(FaceRecDBParam* param, FaceRecDBResult* result);

    int SaveFaceRecDB(const string& name, const string& faceImageListFileName, const string& faceFeatureFileName);

    void RegisterFeatureCompare(FeatureCompareCB callback, void* context);

    int                 m_faceFeatureCount;
    int                 m_faceCount;

protected:
    mutex               m_dbLock;
    FeatureCompareCB    m_callback;
    void*               m_context;
    int                 m_similarityTopK;
    float               m_sameFaceScoreThreshold;

private:
    int                 m_searchMode;
    int                 m_searchThreadnum;
    long long           m_faceId;

    // std::map<long long, std::vector<std::shared_ptr<FaceFeatureInfo>>>  m_FaceIdFeaturesMap;
    // std::map<long long, std::vector<std::shared_ptr<FaceFeatureInfo>>>  m_MoveOutFaceIdFeaturesMap;
    // std::map<long long, string>  m_FaceIdUUIDMap;
    std::vector<std::vector<std::shared_ptr<FaceFeatureInfo>>>  m_FaceIdFeaturesMap;
    std::vector<std::vector<std::shared_ptr<FaceFeatureInfo>>>  m_MoveOutFaceIdFeaturesMap;
    std::vector<std::string>  m_FaceIdUUIDMap;

    int InsertFace(std::shared_ptr<FaceFeatureInfo> feature, FaceRecDBParam* param, bool isRegister=true);
    int UpdateFace(std::shared_ptr<FaceFeatureInfo> feature, std::shared_ptr<FaceFeatureInfo> matchFeature, FaceRecDBParam* param);
    int MatchFace(std::shared_ptr<FaceFeatureInfo> feature, std::shared_ptr<FaceFeatureInfo> matchFeature, FaceRecDBParam* param);

    int SearchSimilarityTopK(void* feature, int featureSize, std::vector<std::pair<float, std::shared_ptr<FaceFeatureInfo>>>& features, int topk, float scoreThreshold);
    int SearchSimilarityTopKMT(void* feature, int featureSize, std::vector<std::pair<float, std::shared_ptr<FaceFeatureInfo>>>& features, int topk, float scoreThreshold);
};

#endif //#ifndef _FACE_REC_DB_H_
